package cn.edu.ncut.cs.springboot.springsecuritydemo.service.impl;

import cn.edu.ncut.cs.springboot.springsecuritydemo.entity.Role;
import cn.edu.ncut.cs.springboot.springsecuritydemo.entity.User;
import cn.edu.ncut.cs.springboot.springsecuritydemo.entity.UserRole;
import cn.edu.ncut.cs.springboot.springsecuritydemo.repository.RoleRepository;
import cn.edu.ncut.cs.springboot.springsecuritydemo.repository.UserRepository;
import cn.edu.ncut.cs.springboot.springsecuritydemo.repository.UserRoleRepository;
import cn.edu.ncut.cs.springboot.springsecuritydemo.service.SystemService;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SystemServiceImpl implements SystemService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private RoleRepository roleRepository;
    @Autowired
    private UserRoleRepository userRoleRepository;

    @Override
    public List<User> findAllUsers() {
        return userRepository.findAll();
    }

    @Override
    public User findUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }

    @Override
    public User findUserByUsername(String username) {
        List<User> users = userRepository.findByUsername(username);
        return users.isEmpty() ? null : users.get(0);
    }

    @Override
    @Transactional
    public boolean assignRolesToUser(Long userId, List<Long> roleIds) {
        try {
            for (Long roleId : roleIds) {
                UserRole userRole = new UserRole();
                userRole.setUserId(userId);
                userRole.setRoleId(roleId);
                userRole.setGmtCreate(Instant.now());
                userRole.setGmtModified(Instant.now());
                userRoleRepository.save(userRole);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    @Transactional
    public boolean removeRolesFromUser(Long userId, List<Long> roleIds) {
        try {
            for (Long roleId : roleIds) {
                userRoleRepository.deleteByUserIdAndRoleId(userId, roleId);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public List<Role> getRolesByUserId(Long userId) {
        List<UserRole> userRoles = userRoleRepository.findByUserId(userId);
        List<Long> roleIds = userRoles.stream().map(UserRole::getRoleId).collect(Collectors.toList());
        return roleRepository.findAllById(roleIds);
    }
}
